package com.newfiber.business.service.impl;

import com.newfiber.business.constant.BusinessConstants;
import com.newfiber.business.domain.PatrolBasicInfo;
import com.newfiber.business.domain.PatrolTask;
import com.newfiber.business.domain.request.patrolBasicInfo.PatrolBasicInfoQueryRequest;
import com.newfiber.business.domain.request.patrolStatistics.PatrolStatisticsQueryRequest;
import com.newfiber.business.domain.request.patrolStatistics.PatrolUserStatisticRequest;
import com.newfiber.business.domain.response.patrolStatistics.CaseCountResult;
import com.newfiber.business.domain.response.patrolStatistics.CaseFinishRateResult;
import com.newfiber.business.domain.response.patrolStatistics.PatrolAttendanceRate;
import com.newfiber.business.domain.response.patrolStatistics.PatrolPerson;
import com.newfiber.business.domain.response.patrolStatistics.PatrolStatisticsCaseResult;
import com.newfiber.business.domain.response.patrolStatistics.PatrolStatisticsSeries;
import com.newfiber.business.domain.response.patrolStatistics.PatrolStatisticsTarget;
import com.newfiber.business.domain.response.patrolStatistics.PatrolUserStatisticResponse;
import com.newfiber.business.enums.EPatrolRedisKey;
import com.newfiber.business.enums.EPatrolTaskStatus;
import com.newfiber.business.enums.EPatrolType;
import com.newfiber.business.mapper.PatrolStatisticsMapper;
import com.newfiber.business.service.IPatrolBasicInfoService;
import com.newfiber.business.service.IPatrolCaseService;
import com.newfiber.business.service.IPatrolPathStayService;
import com.newfiber.business.service.IPatrolStatisticsService;
import com.newfiber.business.service.IPatrolTaskService;
import com.newfiber.business.service.IPatrolUserService;
import com.newfiber.common.redis.service.RedisService;
import com.newfiber.common.security.utils.DictUtils;
import com.newfiber.system.api.domain.SysDictData;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

/**
 * 巡查统计 实现类
 * date: 2023/3/1 下午 04:23
 *
 * @author: LuFan
 * @since JDK 1.8
 */
@Service
public class PatrolStatisticsServiceImpl implements IPatrolStatisticsService {

    @Resource
    private IPatrolBasicInfoService patrolBasicInfoService;

    @Resource
    private PatrolStatisticsMapper patrolStatisticsMapper;

    @Resource
    private IPatrolCaseService patrolCaseService;

    @Resource
    private IPatrolUserService patrolUserService;

    @Resource
    private IPatrolTaskService patrolTaskService;

    @Resource
    private IPatrolPathStayService patrolPathStayService;

    @Resource
    private RedisService redisService;

    @Override
    public PatrolAttendanceRate attendanceRate(PatrolStatisticsQueryRequest request) {
        return patrolStatisticsMapper.attendanceRate(request);
    }

    @Override
    public List<PatrolPerson> patrolPerson(PatrolStatisticsQueryRequest request) {
        return patrolStatisticsMapper.patrolPerson(request);
    }

    @Override
    public PatrolStatisticsCaseResult caseSource(PatrolStatisticsQueryRequest request) {
        PatrolStatisticsCaseResult result = new PatrolStatisticsCaseResult();

        // 查询巡查基本信息
        queryPatrolBasicInfo(request, result);

        // 查询具体case source对应的数据
        List<PatrolStatisticsSeries> patrolStatisticsSeriesList = new ArrayList<>();
        List<SysDictData> caseSources = DictUtils.getDictCache(BusinessConstants.CASE_SOURCE);
        for (SysDictData caseSource : caseSources) {
            PatrolStatisticsSeries patrolStatisticsSeries = new PatrolStatisticsSeries();
            patrolStatisticsSeries.setName(caseSource.getDictLabel());
            List<Integer> count = patrolStatisticsMapper.queryCaseSource(caseSource.getDictValue(), request);
            patrolStatisticsSeries.setData(count);
            patrolStatisticsSeriesList.add(patrolStatisticsSeries);
        }
        return getPatrolStatisticsCaseResult(result, patrolStatisticsSeriesList);
    }

    @Override
    public PatrolStatisticsCaseResult patrolCaseType(PatrolStatisticsQueryRequest request) {
        PatrolStatisticsCaseResult result = new PatrolStatisticsCaseResult();

        // 查询巡查基本信息
        queryPatrolBasicInfo(request, result);

        // 查询具体case type对应的数据
        List<PatrolStatisticsSeries> patrolStatisticsSeriesList = new ArrayList<>();
        List<SysDictData> caseTypes;
        if (EPatrolType.River.getCode().equals(request.getPatrolType())) {
            caseTypes = DictUtils.getDictCache(BusinessConstants.CASE_TYPE);
        } else if (EPatrolType.Pipeline.getCode().equals(request.getPatrolType())) {
            caseTypes = DictUtils.getDictCache(BusinessConstants.PIPELINE_CASE_TYPE);
        } else {
            caseTypes = DictUtils.getDictCache(BusinessConstants.CASE_TYPE);
            caseTypes.addAll(DictUtils.getDictCache(BusinessConstants.PIPELINE_CASE_TYPE));
        }
        List<SysDictData> sortedCaseTypes = caseTypes.stream().sorted(Comparator.comparing(SysDictData::getDictLabel)).collect(Collectors.toList());
        for (SysDictData caseType : sortedCaseTypes) {
            PatrolStatisticsSeries patrolStatisticsSeries = new PatrolStatisticsSeries();
            patrolStatisticsSeries.setName(caseType.getDictLabel());
            List<Integer> count = patrolStatisticsMapper.queryCaseType(caseType.getDictValue(), request);
            patrolStatisticsSeries.setData(count);
            patrolStatisticsSeriesList.add(patrolStatisticsSeries);
        }

        return getPatrolStatisticsCaseResult(result, patrolStatisticsSeriesList);
    }

    @NotNull
    private static PatrolStatisticsCaseResult getPatrolStatisticsCaseResult(PatrolStatisticsCaseResult result, List<PatrolStatisticsSeries> patrolStatisticsSeriesList) {
        for (int i = 0; i < patrolStatisticsSeriesList.size(); i++) {
            List<Integer> data = patrolStatisticsSeriesList.get(i).getData();
            for (int j = 0; j < data.size(); j++) {
                if (0 != data.get(j)) {
                    result.setSeries(patrolStatisticsSeriesList);
                    return result;
                }
            }
        }
        return new PatrolStatisticsCaseResult();
    }

    private void queryPatrolBasicInfo(PatrolStatisticsQueryRequest request, PatrolStatisticsCaseResult result) {
        // 查询巡查基本信息
        PatrolBasicInfoQueryRequest patrolBasicInfoQueryRequest = new PatrolBasicInfoQueryRequest();
        if (!BusinessConstants.ALL.equals(request.getPatrolType())) {
            patrolBasicInfoQueryRequest.setPatrolType(request.getPatrolType());
        }
        List<PatrolBasicInfo> patrolBasicInfo = patrolBasicInfoService.selectList(patrolBasicInfoQueryRequest);

        // 根据id排序
        patrolBasicInfo.sort(Comparator.comparing(PatrolBasicInfo::getId));

        List<PatrolStatisticsTarget> patrolStatisticsTargetList = new ArrayList<>();
        PatrolStatisticsTarget patrolStatisticsTarget = new PatrolStatisticsTarget();
        patrolStatisticsTarget.setType("category");
        List<String> targetStr = new ArrayList<>();
        patrolBasicInfo.forEach(e -> targetStr.add(e.getPatrolTarget()));
        patrolStatisticsTarget.setData(targetStr);
        patrolStatisticsTargetList.add(patrolStatisticsTarget);
        result.setXAxis(patrolStatisticsTargetList);
    }

    @Override
    public List<CaseCountResult> caseType(PatrolStatisticsQueryRequest request) {
        return getCaseCountResults(patrolStatisticsMapper.caseType(request));
    }

    @Override
    public CaseFinishRateResult caseFinishRate(PatrolStatisticsQueryRequest request) {
        return patrolStatisticsMapper.caseFinishRate(request);
    }

    @Override
    public List<CaseCountResult> caseSourceTotal(PatrolStatisticsQueryRequest request) {
        return getCaseCountResults(patrolStatisticsMapper.caseSourceTotal(request));
    }

    @NotNull
    private List<CaseCountResult> getCaseCountResults(List<CaseCountResult> patrolStatisticsMapper) {
        List<CaseCountResult> caseCountResults = patrolStatisticsMapper;
        for (int i = 0; i < caseCountResults.size(); i++) {
            if (0 != caseCountResults.get(i).getCount()) {
                return caseCountResults;
            }
        }
        return new ArrayList<>();
    }

    @Override
    public PatrolUserStatisticResponse patrolUserStatistic(PatrolUserStatisticRequest request) {
        PatrolUserStatisticResponse response = new PatrolUserStatisticResponse();

        // 总人数
        response.setTotalPatrolUserCount(patrolUserService.patrolUserDistinctCount(request.getPatrolType()));

        // 实时在线人数
        Collection<String> realtimeTaskIdList = redisService.keys(EPatrolRedisKey.TodayPatrolTask);
        response.setRealtimePatrolUserCount(realtimeTaskIdList.size());
        List<Long> realPatrolTaskIdList = realtimeTaskIdList.stream().map(t -> Long.parseLong(t.split(":")[1])).collect(Collectors.toList());
        response.setRealtimePatrolTask(patrolTaskService.selectList(realPatrolTaskIdList));

        List<PatrolTask> patrolTaskList = patrolTaskService.untilEndDateList(new Date(), request.getPatrolType());

        // 应到任务、人数
        long shouldPatrolUserCount = patrolTaskList.stream().filter(t -> !EPatrolTaskStatus.Done.getCode().equals(t.getStatus())).
                map(PatrolTask::getTaskUserId).distinct().count();
        response.setShouldPatrolUserCount(shouldPatrolUserCount);
        response.setShouldPatrolTaskList(patrolTaskList.stream().filter(t -> !EPatrolTaskStatus.Done.getCode().equals(t.getStatus())).collect(Collectors.toList()));

        // 已完成任务、已完成人数
        List<PatrolTask> donePatrolTaskList = patrolTaskList.stream().filter(t -> EPatrolTaskStatus.Done.getCode().equals(t.getStatus())).collect(Collectors.toList());
        long donePatrolUserCount = donePatrolTaskList.stream().map(PatrolTask::getTaskUserId).distinct().count();
        response.setDonePatrolTaskList(donePatrolTaskList);
        response.setDonePatrolTaskCount(donePatrolTaskList.size());

        // 案件数量
        List<Long> patrolTaskIdList = donePatrolTaskList.stream().map(PatrolTask::getId).collect(Collectors.toList());
        response.setPatrolCaseCount(patrolCaseService.count(patrolTaskIdList));

        response.setDonePatrolUserCount(donePatrolUserCount);

        // 缺勤任务、缺勤人数
        List<PatrolTask> absencePatrolTaskList = patrolTaskList.stream().filter(t -> EPatrolTaskStatus.ToStart.getCode().equals(t.getStatus())
                || EPatrolTaskStatus.Expired.getCode().equals(t.getStatus())).collect(Collectors.toList());
        long absencePatrolUserCount = absencePatrolTaskList.stream().map(PatrolTask::getTaskUserId).distinct().count();
        response.setAbsencePatrolTaskList(absencePatrolTaskList);
        response.setAbsencePatrolUserCount(absencePatrolUserCount);

        // 异常停留人数
        response.setAbnormalStayUserCount(patrolPathStayService.patrolStayUserDistinctCount());

        return response;
    }
}
